#include "sdk.h"
#include "config.h"


#define SCREEN_HEIGHT 272
#define SCREEN_WIDTH  512
#define CMAX_X 60
#define CMAX_Y 38
#define LINESIZE 	512				//in long
#define FRAMESIZE  0xAA000			//in byte

#define TEXTCOLOUR 0x00FFFFFFL
#define BLACK      0x00000000L
#define BLUE       0x00FF0000L
#define RED        0x000000FFL
#define GREEN      0x0000FF00L

#define SECOND_LOADER MBCFW_ROOT"H2.BIN"
#define load_address 0x40010000
#define run_address 0x00010000

int bin_len;
char* binfile;
char* binfile2;

enum{

	BEGIN,

	#ifdef ARK_BIN
	ARK,
	#endif

	#ifdef TNV_BIN
	TNV,
	#endif

	#ifdef TNC_BIN
	TNC,
	#endif

	#ifdef HBL_BIN
	HBL,
	#endif

	END
};

int sel_index = BEGIN+1;

typedef unsigned int  UINT;
typedef void          VOID;
typedef unsigned char BOOL;
#define TRUE  1
#define FALSE 0
#define NULL  0

typedef struct {
  UINT left;
  UINT right;
  UINT top;
  UINT bottom;
} RECT;

typedef struct {
  UINT cx;
  UINT cy;
} SIZE;

typedef struct {
  UINT x;
  UINT y;
} POINT;

// get vram address for character position
unsigned char *GetVramAddr(unsigned long x,unsigned long y);

// print a single character
void PutChar(unsigned long x,unsigned long y,unsigned long color,unsigned long bgcolor,unsigned char ch,char drawfg,char drawbg,char mag);

// print a string
void Print(unsigned long x,unsigned long y,unsigned long color,const char *str);

// x is in pixels rather than character cells
void PrintFine(unsigned long x,unsigned long y,unsigned long color,const char *str);

// clear video ram
void Fillvram(unsigned long color);

void WriteNibble(int x, int y, unsigned char val);

void WriteByte(int x, int y, unsigned char val);

void WriteDword(int x, int y, unsigned long val);

void WriteNibbleDummy(int x, int y, unsigned char val);

void WriteByteDummy(int x, int y, unsigned char val);

void WriteDwordDummy(int x, int y, unsigned long val);

void FillRect(RECT *xirect, unsigned long xicolour);

void MoveToEx(short x, short y);

void LineTo(short x, short y);

void changeBuffer();

void DebugValue(int y, char * label, unsigned long val);

void WriteDecimal(int x, int y, unsigned long val);

void initScreenAndCtrl();

void memcpy(char *dest, char *src, int size);

int strlen(char * xistr);

void createScreenshot();

void memdump();

// font data
const unsigned char font[]={

    // much better charset, by eddie!
    // this is actually the 8x8 neuromancer
    // vga/ega mode font :)
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   // 0x20
    0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00,   // 0x21
    0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,   // 0x22
    0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,   // 0x23
    0x30,0x7C,0xC0,0x78,0x0C,0xF8,0x30,0x00,   // 0x24
    0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00,   // 0x25
    0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00,   // 0x26
    0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,   // 0x27
    0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00,   // 0x28
    0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00,   // 0x29
    0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,   // 0x2A
    0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00,   // 0x2B
    0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,   // 0x2C
    0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,   // 0x2D
    0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,   // 0x2E
    0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,   // 0x2F
    0x7C,0xC6,0xCE,0xDE,0xF6,0xE6,0x7C,0x00,   // 0x30
    0x30,0x70,0x30,0x30,0x30,0x30,0xFC,0x00,   // 0x31
    0x78,0xCC,0x0C,0x38,0x60,0xCC,0xFC,0x00,   // 0x32
    0x78,0xCC,0x0C,0x38,0x0C,0xCC,0x78,0x00,   // 0x33
    0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00,   // 0x34
    0xFC,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00,   // 0x35
    0x38,0x60,0xC0,0xF8,0xCC,0xCC,0x78,0x00,   // 0x36
    0xFC,0xCC,0x0C,0x18,0x30,0x30,0x30,0x00,   // 0x37
    0x78,0xCC,0xCC,0x78,0xCC,0xCC,0x78,0x00,   // 0x38
    0x78,0xCC,0xCC,0x7C,0x0C,0x18,0x70,0x00,   // 0x39
    0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,   // 0x3A
    0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x60,   // 0x3B
    0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x00,   // 0x3C
    0x00,0x00,0xFC,0x00,0x00,0xFC,0x00,0x00,   // 0x3D
    0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,   // 0x3E
    0x78,0xCC,0x0C,0x18,0x30,0x00,0x30,0x00,   // 0x3F
    0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00,   // 0x40
    0x30,0x78,0xCC,0xCC,0xFC,0xCC,0xCC,0x00,   // 0x41
    0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00,   // 0x42
    0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00,   // 0x43
    0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00,   // 0x44
    0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00,   // 0x45
    0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00,   // 0x46
    0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3E,0x00,   // 0x47
    0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,   // 0x48
    0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,   // 0x49
    0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,   // 0x4A
    0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00,   // 0x4B
    0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,   // 0x4C
    0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00,   // 0x4D
    0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00,   // 0x4E
    0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00,   // 0x4F
    0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,   // 0x50
    0x78,0xCC,0xCC,0xCC,0xDC,0x78,0x1C,0x00,   // 0x51
    0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00,   // 0x52
    0x78,0xCC,0xE0,0x70,0x1C,0xCC,0x78,0x00,   // 0x53
    0xFC,0xB4,0x30,0x30,0x30,0x30,0x78,0x00,   // 0x54
    0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFC,0x00,   // 0x55
    0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,   // 0x56
    0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,   // 0x57
    0xC6,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00,   // 0x58
    0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00,   // 0x59
    0xFE,0xC6,0x8C,0x18,0x32,0x66,0xFE,0x00,   // 0x5A
    0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00,   // 0x5B
    0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,   // 0x5C
    0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00,   // 0x5D
    0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,   // 0x5E
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,   // 0x5F
    0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,   // 0x60
    0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00,   // 0x61
    0xE0,0x60,0x60,0x7C,0x66,0x66,0xDC,0x00,   // 0x62
    0x00,0x00,0x78,0xCC,0xC0,0xCC,0x78,0x00,   // 0x63
    0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00,   // 0x64
    0x00,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00,   // 0x65
    0x38,0x6C,0x60,0xF0,0x60,0x60,0xF0,0x00,   // 0x66
    0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8,   // 0x67
    0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00,   // 0x68
    0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00,   // 0x69
    0x0C,0x00,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,   // 0x6A
    0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00,   // 0x6B
    0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,   // 0x6C
    0x00,0x00,0xCC,0xFE,0xFE,0xD6,0xC6,0x00,   // 0x6D
    0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0x00,   // 0x6E
    0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x00,   // 0x6F
    0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0,   // 0x70
    0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E,   // 0x71
    0x00,0x00,0xDC,0x76,0x66,0x60,0xF0,0x00,   // 0x72
    0x00,0x00,0x7C,0xC0,0x78,0x0C,0xF8,0x00,   // 0x73
    0x10,0x30,0x7C,0x30,0x30,0x34,0x18,0x00,   // 0x74
    0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00,   // 0x75
    0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00,   // 0x76
    0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x6C,0x00,   // 0x77
    0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00,   // 0x78
    0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8,   // 0x79
    0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00,   // 0x7A
    0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00,   // 0x7B
    0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,   // 0x7C
    0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00,   // 0x7D
    0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,   // 0x7E
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};

unsigned char *vramtop=(unsigned char *)0x04000000;
unsigned long drawframe;
POINT gcursor;

void memcpy(char *dest, char *src, int size)
{
  while (size--)
  {
    *dest++ = *src++;
  }
}

// get vram address for character position
unsigned char *GetVramAddr(unsigned long x,unsigned long y)
{
	return vramtop+(drawframe?FRAMESIZE:0)+x*4+y*LINESIZE*4+0x40000000;
}

// print a single character
void PutChar(unsigned long x,unsigned long y,unsigned long color,unsigned long bgcolor,unsigned char ch,char drawfg,char drawbg,char mag)
{
	unsigned char *vptr0;		//pointer to vram
	unsigned char *vptr;		//pointer to vram
	const unsigned char *cfont;		//pointer to font
	unsigned long cx,cy;
	unsigned long b;
	char mx,my;

	cfont=font+ch*8;

	vptr0=GetVramAddr(x,y);

	for (cy=0; cy<8; cy++)
	{
		for (my=0; my<mag; my++)
		{
			vptr=vptr0;
			b=0x80;
			for (cx=0; cx<8; cx++)
			{
				for (mx=0; mx<mag; mx++)
				{
					if ((*cfont&b)!=0)
					{
						if (drawfg)
            {
              *(unsigned long *)vptr=color;
            }
					}
          else
          {
						if (drawbg)
            {
              *(unsigned long *)vptr=bgcolor;
            }
					}
					vptr+=4;
				}
				b=b>>1;
			}
			vptr0+=LINESIZE*4; // 2
		}
		cfont++;
	}
}

// print a string
void Print(unsigned long x,unsigned long y,unsigned long color,const char *str)
{
	while (*str!=0 && x<CMAX_X && y<CMAX_Y) {
		PutChar(x*8,y*8,color,0,*str,1,1,1);
		str++;
		x++;
		if (x>=CMAX_X) {
			x=0;
			y++;
		}
	}
}

// x is in pixels rather than character cells
void PrintFine(unsigned long x,unsigned long y,unsigned long color,const char *str)
{
	while (*str!=0 && x<(CMAX_X*8) && y<CMAX_Y) {
		PutChar(x,y*8,color,0,*str,1,1,1);
		str++;
		x+=8;
		if (x>=(CMAX_X*8)) {
			x=0;
			y++;
		}
	}
}

// clear video ram
void Fillvram(unsigned long color)
{
	unsigned char *vptr0;		//pointer to vram
	unsigned long i;

	vptr0=GetVramAddr(0,0);

	for (i=0; i<(FRAMESIZE/4); i++)
	{
		*(unsigned long *)vptr0=color;
		vptr0+=4;
	}
}

void WriteNibble(int x, int y, unsigned char val)
{
  if (val > 9)
  {
    val = 'A' + val - 10;
  }
  else
  {
    val = '0' + val;
  }
	PutChar(x*8,y*8,TEXTCOLOUR,0,val,1,1,1);
}

void WriteByte(int x, int y, unsigned char val)
{
  char lchr;

  lchr = (val & 0xF0) >> 4;
  WriteNibble(x,y,lchr);
  lchr = (val & 0xF);
  WriteNibble(x+1,y,lchr);
}

void WriteDword(int x, int y, unsigned long val)
{
  WriteByte(x,y,(val & 0xFF000000L) >> 24);
  WriteByte(x+2,y,(val & 0xFF0000L) >> 16);
  WriteByte(x+4,y,(val & 0xFF00L) >> 8);
  WriteByte(x+6,y,(val & 0xFFL));
}

void WriteNibbleDummy(int x, int y, unsigned char val)
{
  if (val > 9)
  {
    val = 'A' + val - 10;
  }
  else
  {
    val = '0' + val;
  }
	PutChar(x*8,y*8,0,0,val,1,1,1);
}

void WriteByteDummy(int x, int y, unsigned char val)
{
  char lchr;

  lchr = (val & 0xF0) >> 4;
  WriteNibbleDummy(x,y,lchr);
  lchr = (val & 0xF);
  WriteNibbleDummy(x+1,y,lchr);
}

void WriteDwordDummy(int x, int y, unsigned long val)
{
  WriteByteDummy(x,y,(val & 0xFF000000L) >> 24);
  WriteByteDummy(x+2,y,(val & 0xFF0000L) >> 16);
  WriteByteDummy(x+4,y,(val & 0xFF00L) >> 8);
  WriteByteDummy(x+6,y,(val & 0xFFL));
}

void FillRect(RECT *xirect, unsigned long xicolour)
{
  unsigned long *vptrl;
  unsigned char *vptrc;
  int      y;

  for (y = xirect->top; y < xirect->bottom; y++)
  {
    int x = xirect->left;
    vptrc = GetVramAddr(x,y);
    vptrl = (unsigned long*)vptrc;

    while (x < xirect->right)
    {
      *vptrl++ = xicolour;
      x++;
    }
  }
}

void MoveToEx(short x, short y)
{
  gcursor.x = x;
  gcursor.y = y;
}

void LineTo(short x, short y)
{
  // XXX to do
}

void changeBuffer()
{
  sceDisplayWaitVblankStart();

	sceDisplaySetFrameBuf(
      (void*)GetVramAddr(0,0),
      512,
    	PSP_DISPLAY_PIXEL_FORMAT_8888
      ,0);

	drawframe=(drawframe?0:1);
}

void DebugValue(int y, char * label, unsigned long val)
{
  Print(0,y,TEXTCOLOUR,label);
  WriteDword(10,y,val);
}

void WriteDecimal(int x, int y, unsigned long val)
{
  unsigned long divisor = 10000000L;
  unsigned char nibble;

  val = val % 100000000L;

  while (divisor > 0)
  {
    nibble = val / divisor;

    WriteNibble(x, y, nibble);

    val = val - (nibble * divisor);
    x++;
    divisor /= 10;
  }
}

void initScreenAndCtrl()
{
  drawframe = 0;
	sceDisplaySetMode(0,SCREEN_WIDTH,SCREEN_HEIGHT);

	sceDisplaySetFrameBuf(
      (void*)vramtop,
      512,
    	PSP_DISPLAY_PIXEL_FORMAT_8888
      ,1);
	Fillvram(0x00000000);
  drawframe = 1;
	Fillvram(0x00000000);
  sceCtrlSetSamplingMode(1);
}

int strlen(char * xistr)
{
  int i = 0;
  while (*xistr)
  {
    i++;
  }
  return(i);
}

/*****************************************************************************/
/* Screenshot code borrowed from PSPSokoban: Niklas Nordebo                  */
/*****************************************************************************/
#define PIXELSIZE 4
void createScreenshot() {

  unsigned char  bmpHeader24[] = { 0x42, 0x4d, 0x38, 0xfa, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  unsigned char  buffer[SCREEN_WIDTH*3];
  unsigned char  r,g,b;
  int bufferIndex = 0;
  unsigned long p;
  int file;
  unsigned char *vptr;
  unsigned char *vptr0;
  int i=0;
  int e=0;
  char savePath[] = "ms0:/screen.bmp";

  file = sceIoOpen(savePath,PSP_O_CREAT | PSP_O_TRUNC | PSP_O_RDWR, 0777);

  // write bmp header
  sceIoWrite(file,bmpHeader24,54);

  // write bmp data
  vptr0 = GetVramAddr(0,271);

  for(i=0; i<SCREEN_HEIGHT; i++)
    {
      vptr=vptr0;
      for(e=0; e<480; e++)
	{
	  p = *(unsigned long *)vptr;
	  r = (unsigned char)(p & 0x000000FFL);
	  g = (unsigned char)((p & 0x0000FF00L) >> 8);
	  b = (unsigned char)((p & 0x00FF0000L) >> 16);

	  buffer[bufferIndex] = b;
	  bufferIndex++;
	  buffer[bufferIndex] = g;
	  bufferIndex++;
	  buffer[bufferIndex] = r;
	  bufferIndex++;

	  vptr+=PIXELSIZE;
	}
      // write chunk
      sceIoWrite(file,buffer,480*3);
      bufferIndex=0;
      vptr0-=LINESIZE*4;
    }

  // bmp end
  unsigned char end[] = { 0x00, 0x00 };
  sceIoWrite(file,end,2);

  sceIoClose(file);

}

void memdump()
{
  int file;

  file = sceIoOpen("ms0:/mem.dmp",PSP_O_CREAT | PSP_O_TRUNC | PSP_O_RDWR, 0777);
  sceIoWrite(file,0x08800000, 0x01800000);
  sceIoClose(file);
}

extern unsigned long failedNID;

SceCtrlData gpaddata;

int Paused;

#define INDEX_BLACK      10
#define INDEX_WHITE      1
#define INDEX_PINK       2
#define INDEX_RED        3
#define INDEX_BLUE       4
#define INDEX_GREEN      5
#define INDEX_YELLOW     6
#define INDEX_CYAN       7
#define INDEX_GRAY       9
#define INDEX_DARKGREEN  0
#define RANDOM           rand()%9

#define true 1
#define false !true

unsigned long colours[11];

int color,i;


#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
#define UMASK 0x80000000UL /* most significant w-r bits */
#define LMASK 0x7fffffffUL /* least significant r bits */
#define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
#define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))

static unsigned long state[N]; /* the array for the state vector  */
static int left = 1;
static int initf = 0;
static unsigned long *next;

/* initializes state[N] with a seed */
static void
init_genrand(s)
    unsigned long s;
{
    int j;
    state[0]= s & 0xffffffffUL;
    for (j=1; j<N; j++) {
        state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); 
        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
        /* In the previous versions, MSBs of the seed affect   */
        /* only MSBs of the array state[].                        */
        /* 2002/01/09 modified by Makoto Matsumoto             */
        state[j] &= 0xffffffffUL;  /* for >32 bit machines */
    }
    left = 1; initf = 1;
}

/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
static void
init_by_array(unsigned long init_key[], int key_length)
{
    int i, j, k;
    init_genrand(19650218UL);
    i=1; j=0;
    k = (N>key_length ? N : key_length);
    for (; k; k--) {
        state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL))
          + init_key[j] + j; /* non linear */
        state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++; j++;
        if (i>=N) { state[0] = state[N-1]; i=1; }
        if (j>=key_length) j=0;
    }
    for (k=N-1; k; k--) {
        state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL))
          - i; /* non linear */
        state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i>=N) { state[0] = state[N-1]; i=1; }
    }

    state[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
    left = 1; initf = 1;
}

static void
next_state()
{
    unsigned long *p=state;
    int j;

    /* if init_genrand() has not been called, */
    /* a default initial seed is used         */
    if (initf==0) init_genrand(5489UL);

    left = N;
    next = state;
    
    for (j=N-M+1; --j; p++) 
        *p = p[M] ^ TWIST(p[0], p[1]);

    for (j=M; --j; p++) 
        *p = p[M-N] ^ TWIST(p[0], p[1]);

    *p = p[M-N] ^ TWIST(p[0], state[0]);
}

/* generates a random number on [0,0xffffffff]-interval */
static unsigned long
genrand_int32(void)
{
    unsigned long y;

    if (--left == 0) next_state();
    y = *next++;

    /* Tempering */
    y ^= (y >> 11);
    y ^= (y << 7) & 0x9d2c5680UL;
    y ^= (y << 15) & 0xefc60000UL;
    y ^= (y >> 18);

    return y;
}

/* generates a random number on [0,1) with 53-bit resolution*/
static double
genrand_real(void) 
{ 
    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
    return(a*67108864.0+b)*(1.0/9007199254740992.0); 
} 

static unsigned long rand(void) __attribute__((alias("genrand_int32")));

void InitGlobals()
{
	colours[10] = 0x00000000L;
 	colours[1] = 0x00FFFFFFL;
 	colours[2] = 0x00FF00FFL;
 	colours[3] = 0x000000FFL;
 	colours[4] = 0x00FF0000L;
 	colours[5] = 0x0000FF00L;
 	colours[6] = 0x0000FFFFL;
 	colours[7] = 0x00FFFF00L;
 	colours[8] = 0x00FFFF88L;
 	colours[9] = 0x00888888L;
 	colours[0] = 0x00008800L;
	
 	i=0;
 	color=INDEX_GRAY;
}

void load_bin(){
        // binary loader adapted from TN to work with pretty much every binary file
        int pathlen = strlen(MBCFW_ROOT);

		/* Read binfile to memory */
		SceUID fd = sceIoOpen(binfile, PSP_O_RDONLY, 0);
		sceIoRead(fd, (void *)load_address, bin_len);
		sceIoClose(fd);

		/* args: length of savedata path without "TV.BIN" */
		/* argp: the path */
		/* Example: call(28, "ms0:/PSP/SAVEDATA/NPEZ00176/TV.BIN"); */
		void (* call)(SceSize args, void *argp, char* binpath) = (void *)run_address;
        sceKernelDcacheWritebackAll();
		call(pathlen, binfile, binfile2);
}

void ProcessKeys(unsigned long xikeys)
{
  if (xikeys & PSP_CTRL_UP || xikeys & PSP_CTRL_RIGHT) {
             if(color>=10) { color=0; }
             else { color++; }
             if(sel_index>BEGIN+1) sel_index--;
             else sel_index=END-1;
             Sleep(100);
  }
  if (xikeys & PSP_CTRL_DOWN || xikeys & PSP_CTRL_LEFT) {
             if(color<0) { color=10; }
             else { color--; }
             if(sel_index<END-1) sel_index++;
             else sel_index=BEGIN+1;
             Sleep(100);
  }
  if (xikeys & PSP_CTRL_CROSS){
             switch (sel_index){

             #ifdef ARK_BIN
             case ARK:
                   binfile=SECOND_LOADER;
                   bin_len = 0x10000;
                   binfile2 = ARK_BIN;
                   load_bin();
                   break;
             #endif

             #ifdef TNV_BIN
             case TNV:
                   binfile = TNV_BIN;
                   bin_len = 16 * 1024;
                   binfile2 = "";
                   load_bin();
                   break;
             #endif

             #ifdef TNC_BIN
             case TNC:
                   binfile = TNC_BIN;
                   bin_len = 16 * 1024;
                   binfile2 = "";
                   load_bin();
                   break;
             #endif

             #ifdef HBL_BIN
             case HBL:
                   binfile = SECOND_LOADER;
                   bin_len = 0x10000;
                   binfile2 = HBL_BIN;
                   load_bin();
                   break;
             #endif

             default: break;
             }
  }
  if (xikeys & PSP_CTRL_HOME) // if home is pressed
  {
             for(i=0;i<278;i++) {     
                                Fillvram(0x00FFFFFFL);               
                                changeBuffer();                                        // flip screen to display what i just wrote
                                Sleep(10);                                           // delay for 1.5 seconds
             }
             changeBuffer();                                        // flip the buffer back to drawing mode for fade* functions
             fadeIn();                                              // fadeIn  -----|  Nice Cute
             fadeOut();                                             // fadeOut -----|    Effect
		   sceKernelExitGame();                             // exit
  }

  if (xikeys & PSP_CTRL_TRIANGLE) createScreenshot();
}

int Sleep(unsigned int xicount)
{
  int ldummy = 2;
  unsigned int i;
  unsigned int j;

  for (i=0; i < xicount; i++)
  {
    for (j=0; j < 65000; j++)
    {
      ldummy = ldummy * ldummy;
    }
  }

  return(ldummy);
}

void fadeIn()
{
  int i;

  for (i = 0; i < 16; i+=3)
  {
    Fillvram(0x00111111 * i);
    sceDisplayWaitVblankStart();
    changeBuffer();
  }
}

void fadeOut()
{
  int i;

  for (i = 15; i >= 0; i--)
  {
    Fillvram(0x00111111 * i);
    sceDisplayWaitVblankStart();
    changeBuffer();
  }

	Fillvram(0);
	changeBuffer();
	Fillvram(0);
}

RECT pixel;
void drawPixel(int x, int y, int sizex, int sizey, unsigned long color) {
     pixel.top = y;
     pixel.left = x;
     pixel.bottom = y+sizey;
     pixel.right = x+sizex;
     
     FillRect(&pixel, color);
}

typedef struct snoflake {
        int x,y,flake;
} snoflake;
snoflake snowflake[100];

void _start(unsigned long, unsigned long *) __attribute__ ((section (".text.start")));
void _start(unsigned long arglen, unsigned long *argp)
{
   
	sceKernelDcacheWritebackAll();
  int a=0,sway=0;

  InitGlobals();

  initScreenAndCtrl();

  fadeIn();
  fadeOut();

  Print (22,15,colours[INDEX_GREEN]," - Hello World! -");
  changeBuffer();
  Sleep(1000);
  changeBuffer();

  fadeIn();
  fadeOut();

  for (i = 0; i<100; i++) {
       snowflake[i].x = rand()%480;
       snowflake[i].y = rand()%272;
       snowflake[i].flake = rand()%3;
  }


  for(;;)
  {
     gpaddata.Buttons = 0;

     sceCtrlReadBufferPositive(&gpaddata,1);

     ProcessKeys(gpaddata.Buttons);
    
     Fillvram(colours[INDEX_BLACK]);    

     for (a = 0;a<100;a++) {
          sway = rand()%4;
          if (sway == 1 || sway == 2) {
             snowflake[a].x -= 1;
          } 
          if (sway == 3 || sway == 4) {
             snowflake[a].x += 1;
          }
          snowflake[a].y += rand()%4;
          if (snowflake[a].y > 272) {
               snowflake[a].y = 0;
               snowflake[a].x = rand()%480;
          }
          if(snowflake[a].flake==0) {
                                 drawPixel(snowflake[a].x,snowflake[a].y,1,1,colours[color]);
          }
          if(snowflake[a].flake==1) {
                                    drawPixel(snowflake[a].x,snowflake[a].y,2,2,colours[color]);
          }
          if(snowflake[a].flake==2) {
                                    drawPixel(snowflake[a].x,snowflake[a].y,3,3,colours[color]);
          }
     }

     drawPixel(0,247,480,272,colours[INDEX_GRAY]); // ground

     #ifdef ARK_BIN
     Print (0,ARK,colours[INDEX_GRAY],"  ARK");
     #endif

     #ifdef TNV_BIN
     Print (0,TNV,colours[INDEX_GRAY],"  TNV");
     #endif

     #ifdef TNC_BIN
     Print (0,TNC,colours[INDEX_GRAY],"  TNC");
     #endif

     #ifdef HBL_BIN
     Print (0,HBL,colours[INDEX_GRAY],"  HBL");
     #endif

     if (END > 1) Print (0,sel_index,colours[INDEX_GRAY],">");

     Print (0,END+5,colours[INDEX_GRAY],"multiBootCFW by Acid_Snake");

     changeBuffer();
  }

}


